using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Trippy.Animation;
using Trippy.Levels;
using Trippy.CollidableGameComponents.Projectiles;
using Trippy.Abilities;

// these enemies are pathing enemies
namespace Trippy.CollidableGameComponents.Agents
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    /// 
    public enum EnemyState { None, Grounded }

    public class Enemy : Agent
    {
        public static Texture2D SpriteSheet { get; private set; }
        public enum CastState { Idle, Casting, Casted }
        public enum Facing { Left, Right }
        protected CastState castState;
        protected float timer = 1f;
        EffectAnimation CastingAnimation;
        Facing direction = Facing.Left;

        protected override void LoadContent()
        {
            if (SpriteSheet == null) SpriteSheet = CurrentLevel.Game.Content.Load<Texture2D>("Sprites/Agents/wizard_sheet");
            Sprite = new AnimatedSprite(this, SpriteSheet, 58, 54, 0, 0, 0, 0, 3, 1f);
            base.LoadContent();
        }

        public override void Draw(GameTime gameTime)
        {
            StandardDraw(gameTime);
            base.Draw(gameTime);
        }

        public EnemyState State { get; protected set; }

        public Enemy(Level level)
            : base(level)
        {
            castState = CastState.Idle;
            State = EnemyState.None;
        }

        public override void HitGround(float y, Vector2 vel = new Vector2())
        {
            State = EnemyState.Grounded;
            base.HitGround(y);
        }


        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>

        public override void Update(GameTime gameTime)
        {
            float elapsedTime = TrippyUtilities.CalculateElapsedTime(gameTime);
            timer -= elapsedTime;
            if (timer <= 0)
            {
                if (castState == CastState.Idle)
                {
                    CastingAnimation = new EffectAnimation(CurrentLevel,
                        CurrentLevel.Game.Content.Load<Texture2D>("Sprites/Effects/castfire"),
                        64, 64, 0, 0, 0, 0, 15, 0.3f, 20, Position);
                    CastingAnimation.AttachToComponent(this);
                    castState = CastState.Casting;
                    timer = 1f;
                }
                else if (castState == CastState.Casting)
                {
                    CastingAnimation.StopAnimation();
                    EnemyFireball ef = new EnemyFireball(CurrentLevel);
                    if (direction == Facing.Left)
                    {
                        ef.Position = new Vector2(BoundingBox.Left - 40f, Position.Y);
                        ef.Velocity = new Vector2(-200f, 0f);
                    }
                    else
                    {
                        ef.Position = new Vector2(BoundingBox.Right + 40f, Position.Y);
                        ef.Velocity = new Vector2(200f, 0f);
                    }
                    ef.MarkForAddition();
                    timer = 1f;
                    castState = CastState.Casted;
                }
                else
                {
                    timer = 1f;
                    castState = CastState.Idle;
                }
                Sprite.Step();
            }

            if (CurrentLevel.Hero.Position.X < Position.X)
            {
                direction = Facing.Left;
                Sprite.ChangeAnimation(0);
            }
            else
            {
                direction = Facing.Right;
                Sprite.ChangeAnimation(1);
            }

            UpdateStandardPhysics(elapsedTime);

            base.Update(gameTime);
        }

        protected override void CollisionHandler(CollidableGameComponent component, CollidableGameComponent.CollisionSide side)
        {
            if (component is Hero)
            {
                Hero h = (Hero)component;
                switch (side)
                {
                    case CollisionSide.Top:
                        h.Bounce(BoundingBox.Top);
                        break;
                    case CollisionSide.Right:
                        h.HitLeftWall(BoundingBox.Right);
                        break;
                    case CollisionSide.Bottom:
                        h.HitCeiling(BoundingBox.Bottom);
                        break;
                    case CollisionSide.Left:
                        h.HitRightWall(BoundingBox.Left);
                        break;
                    default:
                        throw new ArgumentOutOfRangeException("side");
                }
            }

            base.CollisionHandler(component, side);
        }


        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();
        }

        public override void Restore()
        {
            Sprite.Tint = Color.White;
            base.Restore();
        }
    }
}
